# app/models.py
from django.db import models
from django.utils import timezone
import json


class ScheduledTask(models.Model):
    """调度任务模型"""
    name = models.CharField(max_length=255, verbose_name="任务名称")
    description = models.TextField(blank=True, verbose_name="任务描述")
    
    # 任务函数信息
    module_path = models.CharField(max_length=500, verbose_name="模块路径")
    function_name = models.CharField(max_length=255, verbose_name="函数名称")
    args = models.JSONField(default=list, verbose_name="位置参数")
    kwargs = models.JSONField(default=dict, verbose_name="关键字参数")
    
    # 调度配置
    trigger_type = models.CharField(
        max_length=20,
        choices=[
            ('interval', '间隔执行'),
            ('cron', 'Cron表达式'),
            ('date', '定时执行'),
        ],
        verbose_name="触发器类型"
    )
    trigger_config = models.JSONField(default=dict, verbose_name="触发器配置")
    
    # 状态管理
    is_active = models.BooleanField(default=True, verbose_name="是否启用")
    max_instances = models.IntegerField(default=1, verbose_name="最大实例数")
    
    # 时间信息
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    last_run_time = models.DateTimeField(null=True, blank=True, verbose_name="上次运行时间")
    next_run_time = models.DateTimeField(null=True, blank=True, verbose_name="下次运行时间")
    
    # APScheduler job_id
    job_id = models.CharField(max_length=255, unique=True, verbose_name="任务ID")
    
    class Meta:
        verbose_name = "调度任务"
        verbose_name_plural = "调度任务"
        ordering = ['-created_at']
    
    def __str__(self):
        return f"{self.name} ({self.trigger_type})"


class TaskExecutionLog(models.Model):
    """任务执行日志"""
    
    class StatusChoices(models.TextChoices):
        PENDING = 'pending', '等待中'
        RUNNING = 'running', '运行中'
        COMPLETED = 'completed', '已完成'
        FAILED = 'failed', '失败'
        CANCELLED = 'cancelled', '已取消'
    
    # 关联信息
    scheduled_task = models.ForeignKey(
        ScheduledTask, 
        on_delete=models.CASCADE, 
        null=True, 
        blank=True,
        related_name='execution_logs',
        verbose_name="调度任务"
    )
    strategy_id = models.CharField(max_length=255, null=True, blank=True, verbose_name="策略ID")
    
    # 执行信息
    status = models.CharField(
        max_length=20,
        choices=StatusChoices.choices,
        default=StatusChoices.PENDING,
        verbose_name="执行状态"
    )
    start_time = models.DateTimeField(auto_now_add=True, verbose_name="开始时间")
    end_time = models.DateTimeField(null=True, blank=True, verbose_name="结束时间")
    
    # 结果信息
    result = models.JSONField(null=True, blank=True, verbose_name="执行结果")
    error_message = models.TextField(null=True, blank=True, verbose_name="错误信息")
    
    # 执行环境信息
    execution_time = models.FloatField(null=True, blank=True, verbose_name="执行时长(秒)")
    
    class Meta:
        verbose_name = "任务执行日志"
        verbose_name_plural = "任务执行日志"
        ordering = ['-start_time']
        indexes = [
            models.Index(fields=['status', 'start_time']),
            models.Index(fields=['scheduled_task', 'start_time']),
        ]
    
    def __str__(self):
        task_name = self.scheduled_task.name if self.scheduled_task else f"策略-{self.strategy_id}"
        return f"{task_name} - {self.get_status_display()} ({self.start_time.strftime('%Y-%m-%d %H:%M:%S')})"
    
    def save(self, *args, **kwargs):
        # 计算执行时长
        if self.end_time and self.start_time:
            self.execution_time = (self.end_time - self.start_time).total_seconds()
        super().save(*args, **kwargs)


class TaskMetrics(models.Model):
    """任务执行统计"""
    scheduled_task = models.OneToOneField(
        ScheduledTask,
        on_delete=models.CASCADE,
        related_name='metrics',
        verbose_name="调度任务"
    )
    
    # 执行统计
    total_executions = models.IntegerField(default=0, verbose_name="总执行次数")
    successful_executions = models.IntegerField(default=0, verbose_name="成功执行次数")
    failed_executions = models.IntegerField(default=0, verbose_name="失败执行次数")
    
    # 时间统计
    avg_execution_time = models.FloatField(default=0.0, verbose_name="平均执行时长")
    max_execution_time = models.FloatField(default=0.0, verbose_name="最大执行时长")
    min_execution_time = models.FloatField(default=0.0, verbose_name="最小执行时长")
    
    # 最近统计时间
    last_updated = models.DateTimeField(auto_now=True, verbose_name="最后更新时间")
    
    class Meta:
        verbose_name = "任务统计"
        verbose_name_plural = "任务统计"
    
    def __str__(self):
        return f"{self.scheduled_task.name} - 统计"
    
    @property
    def success_rate(self):
        """成功率"""
        if self.total_executions == 0:
            return 0.0
        return (self.successful_executions / self.total_executions) * 100
    
    def update_metrics(self):
        """更新统计数据"""
        logs = self.scheduled_task.execution_logs.all()
        
        self.total_executions = logs.count()
        self.successful_executions = logs.filter(status=TaskExecutionLog.StatusChoices.COMPLETED).count()
        self.failed_executions = logs.filter(status=TaskExecutionLog.StatusChoices.FAILED).count()
        
        # 计算执行时间统计
        completed_logs = logs.filter(
            status=TaskExecutionLog.StatusChoices.COMPLETED,
            execution_time__isnull=False
        )
        
        if completed_logs.exists():
            execution_times = [log.execution_time for log in completed_logs]
            self.avg_execution_time = sum(execution_times) / len(execution_times)
            self.max_execution_time = max(execution_times)
            self.min_execution_time = min(execution_times)
        
        self.save()